package com.lxj.ticket.service.modules.common.utils;

import java.util.Random;

public class HumanReactionTimeSimulator {
    private static final Random random = new Random();

    // 人类基本反应时间范围（单位：毫秒）
    private static final int MIN_BASIC_REACTION = 180;   // 最快反应时间
    private static final int MAX_BASIC_REACTION = 450;   // 最慢反应时间

    // 不同操作类型的基准反应时间
    private static final int CLICK_REACTION_MIN = 200;
    private static final int CLICK_REACTION_MAX = 600;
    private static final int SCROLL_REACTION_MIN = 150;
    private static final int SCROLL_REACTION_MAX = 400;
    private static final int READ_REACTION_MIN = 800;
    private static final int READ_REACTION_MAX = 3000;

    /**
     * 生成模拟人类点击元素的反应时间
     * 适用于爬虫点击按钮、链接等交互元素
     * @return 随机的反应时间（毫秒）
     */
    public static int generateClickReactionTime() {
        return generateReactionTime(CLICK_REACTION_MIN, CLICK_REACTION_MAX);
    }

    /**
     * 生成模拟人类滚动页面的反应时间
     * @return 随机的反应时间（毫秒）
     */
    public static int generateScrollReactionTime() {
        return generateReactionTime(SCROLL_REACTION_MIN, SCROLL_REACTION_MAX);
    }

    /**
     * 生成模拟人类阅读内容的反应时间
     * @return 随机的反应时间（毫秒）
     */
    public static int generateReadReactionTime() {
        return generateReactionTime(READ_REACTION_MIN, READ_REACTION_MAX);
    }

    /**
     * 生成带疲劳效应的连续操作反应时间
     * 模拟长时间操作后反应变慢的现象
     * @param operationCount 连续操作次数
     * @param baseMin 基础最小时间
     * @param baseMax 基础最大时间
     * @return 考虑疲劳后的反应时间
     */
    public static int generateFatigueReactionTime(int operationCount, int baseMin, int baseMax) {
        double fatigueFactor = 1.0;

        // 操作超过10次后开始产生疲劳效应
        if (operationCount > 10) {
            fatigueFactor = 1.0 + (operationCount - 10) * 0.08;
        }

        int baseTime = generateReactionTime(baseMin, baseMax);
        return (int) (baseTime * fatigueFactor);
    }

    /**
     * 核心方法：生成符合正态分布的人类反应时间
     * 使用高斯分布模拟真实人类反应时间的集中趋势
     * @param min 最小反应时间
     * @param max 最大反应时间
     * @return 随机的反应时间
     */
    private static int generateReactionTime(int min, int max) {
        // 使用高斯分布生成更符合人类反应特征的时间
        double mean = (min + max) / 2.0;  // 平均值
        double stdDev = (max - min) / 6.0; // 标准差，覆盖99.7%的数据

        double gaussianValue;
        do {
            gaussianValue = random.nextGaussian() * stdDev + mean;
        } while (gaussianValue < min || gaussianValue > max);

        return (int) gaussianValue;
    }

    /**
     * 生成考虑网络延迟的完整操作时间
     * 包括反应时间 + 网络波动
     * @param baseReactionTime 基础反应时间
     * @return 完整的操作时间
     */
    public static int generateNetworkAdjustedTime(int baseReactionTime) {
        // 网络延迟波动（±100ms）
        int networkVariation = random.nextInt(200) - 100;
        return Math.max(100, baseReactionTime + networkVariation);
    }

    /**
     * 测试方法：演示如何使用反应时间模拟器
     */
//    public static void main(String[] args) {
//        System.out.println("=== 爬虫人类反应时间模拟器测试 ===");
//
//        // 测试点击反应时间
//        System.out.println("\n点击操作反应时间测试:");
//        for (int i = 0; i < 5; i++) {
//            int clickTime = generateClickReactionTime();
//            System.out.printf("第%d次点击反应时间: %d 毫秒%n", i + 1, clickTime);
//        }
//
//        // 测试滚动反应时间
//        System.out.println("\n滚动操作反应时间测试:");
//        for (int i = 0; i < 5; i++) {
//            int scrollTime = generateScrollReactionTime();
//            System.out.printf("第%d次滚动反应时间: %d 毫秒%n", i + 1, scrollTime);
//        }
//
//        // 测试疲劳效应
//        System.out.println("\n疲劳效应测试:");
//        for (int i = 1; i <= 15; i++) {
//            int fatigueTime = generateFatigueReactionTime(i, CLICK_REACTION_MIN, CLICK_REACTION_MAX);
//            System.out.printf("连续第%d次操作: %d 毫秒%n", i, fatigueTime);
//        }
//
//        // 测试完整网络操作时间
//        System.out.println("\n网络调整时间测试:");
//        int baseTime = generateClickReactionTime();
//        int adjustedTime = generateNetworkAdjustedTime(baseTime);
//        System.out.printf("基础时间: %d 毫秒, 网络调整后: %d 毫秒%n", baseTime, adjustedTime);
//    }
}
